
package com.fsq.xmfsubdomain;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import javax.swing.SwingUtilities;

import org.apache.http.Header;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.xbill.DNS.ExtendedResolver;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.SimpleResolver;

import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioButton;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebErrorEvent;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Modality;
import javafx.stage.Stage;

/**
 * @author root
 */
public class FXMLDocumentController implements Initializable {

    @FXML
    private Button id_newscan;
    @FXML
    private Button id_stop;

    @FXML
    private TextField id_url;
    @FXML
    private Button id_open;
    @FXML
    private Hyperlink id_help;
    @FXML
    private Label id_status;
    @FXML
    private TreeView<String> id_treeview;
    @FXML
    private TableView<Row> id_tableview;
    @FXML
    private TableColumn<?, ?> id_coltarget;
    @FXML
    private TableColumn<?, ?> id_coldomainname;
    @FXML
    private TableColumn<?, ?> id_colip;
    @FXML
    private TableColumn<?, ?> id_colsource;
    @FXML
    private TableColumn<?, ?> id_collevel;
    @FXML
    private TableColumn<?, ?> id_colcontent;
    @FXML
    private AnchorPane id_browserpane;
    @FXML
    private TextArea id_notepad;
    @FXML
    private TextArea id_serverinfo;
    @FXML
    private MenuItem id_expand;
    @FXML
    private MenuItem id_collapse;
    @FXML
    private MenuItem id_send;
    @FXML
    private MenuItem id_cleartreeview;
    @FXML
    private MenuItem id_deleteitems;
    @FXML
    private MenuItem id_sendallips;
    @FXML
    private MenuItem id_sendselectedips;
    @FXML
    private MenuItem id_sendselecteddomainnames;
    @FXML
    private MenuItem id_sendalldomainnames;
    @FXML
    private MenuItem id_senddnandip;
    @FXML
    private MenuItem id_export;
    @FXML
    private MenuItem id_openwithbrowser;

    @FXML
    private ComboBox<String> id_switchdns;

    @FXML
    private MenuItem id_deleterepeated;
    @FXML
    private MenuItem id_cleartableview;

    @FXML
    private MenuItem id_clearthisip;
    @FXML
    private CheckBox id_autovisit;

    private WebView id_webview;

    private ExecutorService threadPool;
    private TreeItem<String> treeItem;
    private LinkedList<ScanTask> taskList = new LinkedList<ScanTask>();
    public static Integer taskCount;
    private Resolver originalDns;

    @Override
    public void initialize(URL url, ResourceBundle rb) {

        // 初始化id_switchdns
        originalDns = Lookup.getDefaultResolver();
        ObservableList<String> dnsServers = FXCollections.observableArrayList("系统默认", "114dns", "googledns", "alidns",
                "baidudns", "腾讯dns", "轮询");
        id_switchdns.setItems(dnsServers);

        // 表格可以多选
        id_tableview.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        // 初始化线程池
        threadPool = Executors.newFixedThreadPool(1);

        // 设置任务数位0
        taskCount = Integer.valueOf(0);
        // 设置根节点
        treeItem = new TreeItem<String>("根节点");
        id_treeview.setRoot(treeItem);

        // 初始化tableview 数据绑定
        id_tableview.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        id_coltarget.setCellValueFactory(new PropertyValueFactory<>("target"));
        id_coldomainname.setCellValueFactory(new PropertyValueFactory<>("domainname"));
        id_colip.setCellValueFactory(new PropertyValueFactory<>("ip"));
        id_colsource.setCellValueFactory(new PropertyValueFactory<>("source"));
        id_collevel.setCellValueFactory(new PropertyValueFactory<>("level"));
        id_colcontent.setCellValueFactory(new PropertyValueFactory<>("content"));

        // 添加浏览器组件
        id_webview = new WebView();
        id_browserpane.getChildren().add(id_webview);
        AnchorPane.setLeftAnchor(id_webview, 0.0);
        AnchorPane.setRightAnchor(id_webview, 0.0);
        AnchorPane.setTopAnchor(id_webview, 0.0);
        AnchorPane.setBottomAnchor(id_webview, 0.0);

        // 设置浏览器的事件处理
        WebEngine eng = id_webview.getEngine();
        eng.locationProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                id_url.setText(newValue);
            }
        });

        eng.setOnError(new EventHandler<WebErrorEvent>() {

            @Override
            public void handle(WebErrorEvent event) {
                System.out.println(event.getMessage());

            }
        });
        eng.load("http://www.cnblogs.com/SEC-fsq/p/5638156.html");

    }

    @FXML
    private void newscan(ActionEvent event) {


        File file = new File(System.getProperty("user.dir") + File.separator + "dict");
        if (!file.isDirectory()) {

            System.out.println("AbsolutePath:" + file.getAbsolutePath());
            new Alert(AlertType.NONE, "当前目录未找到字典文件夹:\r\n" + file.getAbsolutePath(), ButtonType.OK).show();
            return;
        }

        File dictLevel2 = new File(System.getProperty("user.dir") + File.separator + "dict" + File.separator + "level2.txt");
        File dictLevel3 = new File(System.getProperty("user.dir") + File.separator + "dict" + File.separator + "level3.txt");
        File dictLevel4 = new File(System.getProperty("user.dir") + File.separator + "dict" + File.separator + "level4.txt");

        if (!dictLevel2.isFile()) {
            System.out.println("AbsolutePath:" + dictLevel2.getAbsolutePath());
            new Alert(AlertType.NONE, "未找到二级域名爆破字典:\r\n" + dictLevel2.getAbsolutePath(), ButtonType.OK).show();
            return;
        }

        if (!dictLevel3.isFile()) {
            System.out.println("AbsolutePath:" + dictLevel3.getAbsolutePath());
            new Alert(AlertType.NONE, "未找到三级域名爆破字典:\r\n" + dictLevel3.getAbsolutePath(), ButtonType.OK).show();
            return;
        }

        if (!dictLevel4.isFile()) {
            System.out.println("AbsolutePath:" + dictLevel4.getAbsolutePath());
            new Alert(AlertType.NONE, "未找到四级域名爆破字典:\r\n" + dictLevel4.getAbsolutePath(), ButtonType.OK).show();
            return;
        }

        final Stage stage = new Stage();
        stage.initModality(Modality.APPLICATION_MODAL);

        BorderPane borderPane = new BorderPane();
        Scene scene = new Scene(borderPane, 900, 500);
        stage.setScene(scene);
        stage.setTitle("新建任务");
        stage.sizeToScene();

        borderPane.setPadding(new Insets(3, 3, 3, 3));

        borderPane.autosize();

        // broderpane的中间
        VBox vboxCenter = new VBox();
        vboxCenter.setPadding(new Insets(3, 3, 3, 3));
        vboxCenter.setSpacing(3);

        Label lable = new Label("请输入域名：");

        TextArea textArea = new TextArea(null);
        textArea.setPrefWidth(290);
        textArea.setPrefHeight(340);
        textArea.setMaxWidth(-1);
        textArea.setPromptText("jd.com\r\n" + "baidu.com\r\n");
        vboxCenter.getChildren().addAll(lable, textArea);
        VBox.setVgrow(textArea, Priority.ALWAYS);

        // broderpane的右边
        VBox vboxRight = new VBox();
        vboxRight.setPadding(new Insets(3, 3, 3, 3));
        vboxRight.setSpacing(3);

        Label blacklistLabel = new Label("泛域名解析ip黑名单：");

        TextArea textAreaRight = new TextArea(null);
        textAreaRight.setPrefWidth(330);
        textAreaRight.setPrefHeight(340);
        textAreaRight.setMaxWidth(-1);
        textAreaRight.setPromptText("32.123.22.12\r\n" + "32.123.22.123\r\n");
        vboxRight.getChildren().addAll(blacklistLabel, textAreaRight);
        VBox.setVgrow(textAreaRight, Priority.ALWAYS);

        // broderpane的下边
        HBox hboxBottom = new HBox();
        hboxBottom.setPadding(new Insets(1, 1, 1, 1));
        hboxBottom.setSpacing(3);
        hboxBottom.setAlignment(Pos.CENTER_LEFT);

        Button buttonStart = new Button("开始");
        Button buttonCancel = new Button("取消");

        ObservableList<Integer> searchcount = FXCollections.observableArrayList(100, 200, 300, 400, 500, 600, 700, 800,
                900, 1000, 1500, 2000, 3000, 4000, 5000, 8000, 10000);
        ComboBox<Integer> searchcountcb = new ComboBox<Integer>();
        searchcountcb.setItems(searchcount);
        searchcountcb.setPromptText("搜索引擎爬取条数");
        // searchcountcb.setPrefWidth(600);
        HBox.setHgrow(searchcountcb, Priority.ALWAYS);

        ObservableList<Integer> recursive = FXCollections.observableArrayList(2, 3, 4);
        ComboBox<Integer> recursivecb = new ComboBox<Integer>();
        recursivecb.setItems(recursive);
        recursivecb.setPromptText("递归级别");
        // recursivecb.setPrefWidth(600);

        ObservableList<Integer> threads = FXCollections.observableArrayList(1, 5, 10, 20, 30, 50, 80, 100, 150, 200,
                300, 500);
        ComboBox<Integer> threadsInput = new ComboBox<Integer>();
        threadsInput.setItems(threads);
        // threadsInput.setEditable(false);
        threadsInput.setPromptText("爆破线程");

        ObservableList<Integer> threadsSpider = FXCollections.observableArrayList(1, 3, 5, 10, 15, 20);
        ComboBox<Integer> threadsSpiderCb = new ComboBox<Integer>();
        threadsSpiderCb.setItems(threadsSpider);
        // threadsSpiderCb.setEditable(false);
        threadsSpiderCb.setPromptText("爬虫线程");

        ObservableList<Integer> timeout = FXCollections.observableArrayList(300, 500, 800, 1000, 1500, 2000, 3000,
                5000);
        ComboBox<Integer> timeoutInput = new ComboBox<Integer>();
        timeoutInput.setItems(timeout);
        // timeputInput.setEditable(false);
        timeoutInput.setPromptText("超时(毫秒)");

        CheckBox lookupCduan = new CheckBox("反查C段");
        lookupCduan.setSelected(false);

        ObservableList<String> dnsServers = FXCollections.observableArrayList("系统默认", "114dns", "googledns", "alidns",
                "baidudns", "腾讯dns", "轮询");
        ComboBox<String> dnsServersCb = new ComboBox<String>();
        dnsServersCb.setItems(dnsServers);
        dnsServersCb.setEditable(true);
        dnsServersCb.setPromptText("DNS服务器");

        hboxBottom.getChildren().addAll(searchcountcb, recursivecb, timeoutInput, threadsInput, threadsSpiderCb,
                dnsServersCb, lookupCduan, buttonStart, buttonCancel);

        borderPane.setCenter(vboxCenter);
        borderPane.setBottom(hboxBottom);
        borderPane.setRight(vboxRight);

        // rootGroup.getChildren().add(borderPane);
        buttonStart.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {

                // 设置DNS服务器
                String dnsServer = dnsServersCb.getEditor().getText().trim();
                Resolver resolver;
                try {
                    if (dnsServer.equals("") || dnsServer.equals("系统默认")) {
                        resolver = null;
                    } else if (dnsServer.equals("114dns")) {
                        resolver = new SimpleResolver("114.114.114.114");
                    } else if (dnsServer.equals("googledns")) {
                        resolver = new SimpleResolver("8.8.8.8");
                    } else if (dnsServer.equals("alidns")) {
                        resolver = new SimpleResolver("223.5.5.5");
                    } else if (dnsServer.equals("baidudns")) {
                        resolver = new SimpleResolver("180.76.76.76");
                    } else if (dnsServer.equals("腾讯dns")) {
                        resolver = new SimpleResolver("119.29.29.29");
                    } else if (dnsServer.equals("轮询")) {

                        String fileName = System.getProperty("user.dir") + File.separator + "dict" + File.separator
                                + "dns_servers.txt";
                        Reader fi = new FileReader(fileName);
                        BufferedReader br = new BufferedReader(fi);
                        String u;
                        ArrayList<String> dnsservers = new ArrayList<String>();
                        while ((u = br.readLine()) != null) {
                            dnsservers.add(u.trim());
                        }
                        String[] servers = new String[dnsservers.size()];
                        dnsservers.toArray(servers);
                        resolver = new ExtendedResolver(servers);
                        ((ExtendedResolver) resolver).setLoadBalance(true);
                        br.close();
                        fi.close();

                        // ((ExtendedResolver)resolver).
                    } else {
                        resolver = new SimpleResolver(dnsServer);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    new Alert(AlertType.NONE, "DNS服务器输入不合法", ButtonType.CLOSE);
                    return;
                }

                // 设置跑字典线程数
                Integer threads = threadsInput.getValue();
                if (threads == null) {
                    threads = 100;
                }

                // 设置爬虫线程数

                Integer threadsSpider = threadsSpiderCb.getValue();
                if (threadsSpider == null) {
                    threadsSpider = 5;
                }

                // 默认只查询二级域名，不递归
                Integer recursive = recursivecb.getValue();
                if (recursive == null) {
                    recursive = 2;
                }

                // 设置搜索引擎爬取条数
                Integer intsearchcount = searchcountcb.getValue();
                if (intsearchcount == null) {
                    intsearchcount = 500;
                }

                // 设置超时
                Integer timeout = timeoutInput.getValue();
                if (timeout == null) {
                    timeout = 1500;
                }
                // 设置泛域名解析黑名单
                String blackliststr = textAreaRight.getText();
                Set<InetAddress> blacklist = Collections.synchronizedSet(new HashSet<InetAddress>());
                if (blackliststr != null && !blackliststr.equals("")) {
                    String[] blacklistArray = blackliststr.split("\n");
                    for (String host : blacklistArray) {
                        try {
                            blacklist.add(InetAddress.getByName(host.trim()));
                        } catch (UnknownHostException e) {
                            e.printStackTrace();
                        }
                    }
                }

                taskCount++;

                String str = textArea.getText();
                if (str == null) {
                    new Alert(AlertType.NONE, "请输入域名", ButtonType.CLOSE).show();
                    return;
                }
                String[] domains = str.split("\n");

                for (String domain : domains) {
                    ScanTask scanTask = new ScanTask(id_treeview, id_tableview, threads, domain, id_status, recursive,
                            intsearchcount, threadsSpider, resolver, blacklist, lookupCduan.isSelected(), timeout);
                    threadPool.execute(scanTask);
                    taskList.add(scanTask);
                }

                id_status.setText("正在扫描...");
                stage.close();

                Timer timer = new Timer("timer");
                TimerTask timerTask = new TimerTask() {

                    @Override
                    public void run() {
                        ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;
                        Integer count = tpf.getQueue().size();
                        // System.out.println(taskCount);
                        if (taskCount == 0 && count == 0) {
                            timer.cancel();
                            Platform.runLater(new Runnable() {
                                @Override
                                public void run() {
                                    id_status.setText("已完成");
                                }
                            });
                        }
                    }
                };
                timer.schedule(timerTask, 0, 3000);
            }
        });

        buttonCancel.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {
                stage.close();
            }
        });
        stage.centerOnScreen();
        stage.showAndWait();
    }

    @FXML
    private void stop(ActionEvent event) {
        id_status.setText("正在停止...");
        for (ScanTask scanTask : taskList) {
            // scanTask.setStop(true);
        }
        ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;
        tpf.getQueue().clear();

    }

    @FXML
    private void openurl(ActionEvent event) {
        String url = id_url.getText();
        url = url.startsWith("http") ? url : "http://" + url;
        id_webview.getEngine().load(url);

    }

    @FXML
    private void help(ActionEvent event) {
        // 用浏览器打开url，仅支持windows
        // try {
        // Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler
        // http://www.jb51.net");
        // } catch (IOException e1) {
        // // TODO Auto-generated catch block
        // e1.printStackTrace();
        // }
        // 用浏览器打开url
        if (java.awt.Desktop.isDesktopSupported()) {
            try {
                // 创建一个URI实例,注意不是URL
                java.net.URI uri = java.net.URI.create("http://www.cnblogs.com/SEC-fsq/p/5638156.html");
                // 获取当前系统桌面扩展
                java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                // 判断系统桌面是否支持要执行的功能
                if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                    // 获取系统默认浏览器打开链接
                    dp.browse(uri);
                }
            } catch (java.lang.NullPointerException e) {
                // 此为uri为空时抛出异常
            } catch (java.io.IOException e) {
                // 此为无法获取系统默认浏览器
            }
        }
    }

    @FXML
    private void treeviewClicked(MouseEvent event) {
        TreeItem<String> item = id_treeview.getSelectionModel().getSelectedItem();
        if (item == null) {
            return;
        }
        id_serverinfo.clear();
        String host = item.getValue();
        if (host.indexOf("/") == -1) {
            String url = "http://" + host;
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpGet get = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000)
                    .setConnectionRequestTimeout(1000).setSocketTimeout(1000).build();
            get.setConfig(requestConfig);
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        CloseableHttpResponse response = httpclient.execute(get);
                        Header[] headers = response.getAllHeaders();
                        StringBuilder sb = new StringBuilder();
                        for (Header header : headers) {
                            sb.append(header.getName() + ": " + header.getValue() + "\n");
                        }

                        Platform.runLater(new Runnable() {

                            @Override
                            public void run() {
                                id_serverinfo.setText(sb.toString());

                            }
                        });

                    } catch (ClientProtocolException e) {
                        e.printStackTrace();
                        return;
                    } catch (IOException e) {
                        return;
                    } finally {
                        try {
                            httpclient.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }).start();
            if (id_autovisit.isSelected()) {
                id_webview.getEngine().load(url);
            }

        }
    }

    @FXML
    private void tableviewClicked(MouseEvent event) {
        Row row = id_tableview.getSelectionModel().getSelectedItem();
        if (row == null) {
            return;
        }
        id_serverinfo.clear();
        String url = "http://" + row.domainnameProperty().getValueSafe();
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet get = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000).setConnectionRequestTimeout(1000)
                .setSocketTimeout(1000).build();
        get.setConfig(requestConfig);

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    CloseableHttpResponse response = httpclient.execute(get);
                    Header[] headers = response.getAllHeaders();
                    StringBuilder sb = new StringBuilder();
                    for (Header header : headers) {
                        sb.append(header.getName() + ": " + header.getValue() + "\n");
                    }

                    Platform.runLater(new Runnable() {

                        @Override
                        public void run() {
                            id_serverinfo.setText(sb.toString());

                        }
                    });

                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                    return;
                } catch (IOException e) {
                    return;
                } finally {
                    try {
                        httpclient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        }).start();
        if (id_autovisit.isSelected()) {
            id_webview.getEngine().load(url);
        }
    }

    @FXML
    private void cleartreeview(ActionEvent event) {
        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if (ti == null) {
            return;
        }
        if (!ti.isLeaf()) {
            ti.getChildren().clear();
        }
    }

    @FXML
    private void send(ActionEvent event) {
        TreeItem<String> item = id_treeview.getSelectionModel().getSelectedItem();
        sendtonotepad(item);
    }

    // 递归方法
    private void sendtonotepad(TreeItem<String> item) {
        if (item != null) {
            if (item.isLeaf()) {
                id_notepad.appendText(item.getValue() + "\n");
            } else {
                id_notepad.appendText(item.getValue() + "\n");
                for (TreeItem<String> item1 : item.getChildren()) {
                    sendtonotepad(item1);
                }
            }
        }

    }

    @FXML
    private void expandALL(ActionEvent event) {

        expand(treeItem);
        // treeItem.setExpanded(true);
        // ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        // for (TreeItem<String> item : childs) {
        // if (!item.isLeaf()) {
        // item.setExpanded(true);
        // }
        // }

    }

    private void expand(TreeItem<String> ti) {
        if (!ti.isLeaf()) {
            ti.setExpanded(true);
            ObservableList<TreeItem<String>> tichilds = ti.getChildren();
            for (TreeItem<String> treeItem : tichilds) {
                expand(treeItem);
            }
        }

    }

    @FXML
    private void collapseALL(ActionEvent event) {
        treeItem.setExpanded(false);
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                item.setExpanded(false);
            }
        }
    }

    @FXML
    private void cleartableview(ActionEvent event) {
        id_tableview.getItems().clear();
    }

    @FXML
    private void deleteitems(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getSelectionModel().getSelectedItems();
        id_tableview.getItems().removeAll(items);
    }

    @FXML
    private void sendallips(ActionEvent event) {
        ObservableList<Row> allitems = id_tableview.getItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : allitems) {
            sb.append(row.ipProperty().getValueSafe()).append("\n");
        }
        id_notepad.appendText(sb.toString());

    }

    @FXML
    private void sendselectedips(ActionEvent event) {

        ObservableList<Row> allitems = id_tableview.getSelectionModel().getSelectedItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : allitems) {
            sb.append(row.ipProperty().getValueSafe()).append("\n");
        }
        id_notepad.appendText(sb.toString());

    }

    @FXML
    private void sendselecteddomainnames(ActionEvent event) {

        ObservableList<Row> allitems = id_tableview.getSelectionModel().getSelectedItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : allitems) {
            sb.append(row.domainnameProperty().getValueSafe()).append("\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void sendalldomainnames(ActionEvent event) {
        ObservableList<Row> allitems = id_tableview.getItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : allitems) {
            sb.append(row.domainnameProperty().getValueSafe()).append("\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void clearthisip(ActionEvent event) {

        Row row = id_tableview.getSelectionModel().getSelectedItem();
        if (row == null) {
            return;
        }
        String ip = row.ipProperty().getValueSafe();
        for (ScanTask scanTask : taskList) {
            try {
                scanTask.getBlacklist().add(InetAddress.getByName(ip));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        ObservableList<Row> allitems = id_tableview.getItems();
        LinkedList<Row> list = new LinkedList<Row>();
        for (Row row1 : allitems) {
            if (row1.ipProperty().getValueSafe().equals(ip)) {
                list.add(row1);
            }
        }
        allitems.removeAll(list);
    }

    @FXML
    private void senddnandip(ActionEvent event) {
        ObservableList<Row> allitems = id_tableview.getSelectionModel().getSelectedItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : allitems) {
            sb.append(row.domainnameProperty().getValueSafe()).append("	").append(row.ipProperty().getValueSafe())
                    .append("\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void deleterepeated(ActionEvent event) {
        TreeItem<String> item = id_treeview.getSelectionModel().getSelectedItem();
        if (item == null || !item.getValue().contains("级域名")) {
            return;
        }
        if (!item.isLeaf()) {
            ObservableList<TreeItem<String>> childs = item.getChildren();
            HashSet<String> hs = new HashSet<String>();
            for (TreeItem<String> treeItem : childs) {
                hs.add(treeItem.getValue());
            }
            item.getChildren().clear();
            for (String string : hs) {
                item.getChildren().add(new TreeItem<>(string));
            }
        }
    }

    @FXML
    private void switchdns(ActionEvent event) {

        // 设置DNS服务器
        String dnsServer = id_switchdns.getValue();
        Resolver resolver = null;
        try {
            if (dnsServer.equals("") || dnsServer.equals("系统默认")) {
                resolver = originalDns;
            } else if (dnsServer.equals("114dns")) {
                resolver = new SimpleResolver("114.114.114.114");
            } else if (dnsServer.equals("googledns")) {
                resolver = new SimpleResolver("8.8.8.8");
            } else if (dnsServer.equals("alidns")) {
                resolver = new SimpleResolver("223.5.5.5");
            } else if (dnsServer.equals("baidudns")) {
                resolver = new SimpleResolver("180.76.76.76");
            } else if (dnsServer.equals("腾讯dns")) {
                resolver = new SimpleResolver("119.29.29.29");
            } else if (dnsServer.equals("轮询")) {
                String fileName = System.getProperty("user.dir") + File.separator + "dict" + File.separator
                        + "dns_servers.txt";
                Reader fi = new FileReader(fileName);
                BufferedReader br = new BufferedReader(fi);
                String u;
                ArrayList<String> dnsservers = new ArrayList<String>();
                while ((u = br.readLine()) != null) {
                    dnsservers.add(u.trim());
                }
                String[] servers = new String[dnsservers.size()];
                dnsservers.toArray(servers);
                resolver = new ExtendedResolver(servers);
                ((ExtendedResolver) resolver).setLoadBalance(true);
                br.close();
                fi.close();
            } else {
                // donothing
            }

        } catch (Exception e) {
            e.printStackTrace();
            new Alert(AlertType.NONE, "DNS服务器不可用", ButtonType.CLOSE).show();
            return;
        }

        if (resolver != null) {
            Lookup.setDefaultResolver(resolver);
        } else {
            Lookup.setDefaultResolver(originalDns);
        }
        System.out.println(Lookup.getDefaultResolver());
        new Alert(AlertType.NONE, "DNS服务器已切换为" + dnsServer, ButtonType.CLOSE).show();
        ;

    }

    @FXML
    private void export(ActionEvent event) {

        FileChooser fileChooser = new FileChooser();
        // fileChooser.setTitle("");
        fileChooser.getExtensionFilters().addAll(new ExtensionFilter("Text Files", "*.txt"));
        File selectedFile = fileChooser.showSaveDialog(null);
        if (selectedFile != null) {
            FileWriter fw = null;

            try {
                fw = new FileWriter(selectedFile);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            BufferedWriter bw = new BufferedWriter(fw);
            ObservableList<Row> items = id_tableview.getItems();
            for (Row row : items) {
                try {
                    bw.write(row.targetProperty().getValueSafe() + "	" + row.domainnameProperty().getValueSafe()
                            + "	" + row.ipProperty().getValueSafe() + "	" + row.sourceProperty().getValueSafe() + "	"
                            + row.levelProperty().getValueSafe() + "	" + row.contentProperty().getValueSafe());
                    bw.write("\r\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                bw.flush();
                fw.flush();
                bw.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    @FXML
    private void openwithbrowser(ActionEvent event) {
        if (java.awt.Desktop.isDesktopSupported()) {

            Row row = id_tableview.getSelectionModel().getSelectedItem();
            if (row == null) {
                return;
            }
            StringProperty address = row.domainnameProperty();
            String url = address.getValueSafe();
            if (!url.startsWith("http")) {
                url = "http://" + url;
            }

            try {
                // 创建一个URI实例,注意不是URL
                java.net.URI uri = java.net.URI.create(url);
                // 获取当前系统桌面扩展
                java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                // 判断系统桌面是否支持要执行的功能
                if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                    // 获取系统默认浏览器打开链接
                    dp.browse(uri);
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();

                try {
                    Class<URI> clazz = URI.class;
                    Field path = clazz.getDeclaredField("path");
                    Field schemeSpecificPart = clazz.getDeclaredField("schemeSpecificPart");
                    Field string = clazz.getDeclaredField("string");
                    path.setAccessible(true);
                    schemeSpecificPart.setAccessible(true);
                    string.setAccessible(true);

                    int i = url.indexOf("//");
                    String strSchemeSpecificPart = url.substring(i);

                    String s = strSchemeSpecificPart.substring(2);
                    int j = s.indexOf("/");
                    String strpath = s.substring(j);

                    String scheme = url.substring(0, i + 2);
                    String host = s.substring(0, j);
                    host = host.trim();
                    URI uri = URI.create(scheme + host);

                    path.set(uri, strpath);
                    schemeSpecificPart.set(uri, strSchemeSpecificPart);
                    string.set(uri, url);
                    java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                    // 判断系统桌面是否支持要执行的功能
                    if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                        // 获取系统默认浏览器打开链接
                        dp.browse(uri);
                    }

                } catch (Exception ee) {

                }

            } catch (java.lang.NullPointerException e) {
                // 此为uri为空时抛出异常
            } catch (java.io.IOException e) {
                // 此为无法获取系统默认浏览器
            }
        }

    }

}
